package com.gejingyu.aop.example;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * 动态代理工厂类
 */
public class ProxyFactory {

    //被代理的目标对象
    private Object target;

    //通过构造器传入要被代理的对象
    public ProxyFactory(Object target) {
        this.target = target;
    }

    /**
     * <p>Proxy.newProxyInstance()方法一共需要三个参数</p>
     * <p>ClassLoader loader：加载动态生成代理类的类加载器</p>
     * <p>Class<?>[] interfaces：目标对象实现的所有接口的class类型数组</p>
     * <p>InvocationHandler h：设置代理对象实现目标对象方法的过程</p>
     */
    public Object getProxy() {

        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        InvocationHandler invocationHandler = new InvocationHandler() {
            /**
             * @param proxy 代理对象
             * @param method 要调用的目标方法
             * @param args 调用目标方法时的参数列表
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                System.out.println("[动态代理][日志] " + method.getName() + " 方法开始执行，参数是：" + Arrays.toString(args));
                //注意方法传入参数中的proxy是代理类对象，即调用这个invoke方法的对象，而不是要被代理类对象代理的目标对象
                //重写后的invoke方法，要调用目标对象的目标方法
                //如果method.invoke()方法参数使用了传入的proxy，即invoke代理类对象的方法，会反复调用死循环
                Object result = method.invoke(target, args);
                System.out.println("[动态代理][日志] " + method.getName() + " 方法开始结束，结果是：" + result);
                return result;
            }
        };
        return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
    }

}
